﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using Knight.Common.Helper;
using Knlght.Domain;

namespace Knight.Web.Infrastructure.Mvc
{
    /// <summary>
    /// 控制器辅助类
    /// </summary>
    public static class ControllerHelper
    {
        static CriterionRequest createCriterionByString(string value, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And)
        {
            if (!string.IsNullOrEmpty(value))
            {
                bool startWith = false;
                bool endWith = false;
                string temp = value;
                startWith = value.StartsWith("*");
                if (startWith)
                {
                    temp = temp.TrimStart('*');
                }
                endWith = temp.EndsWith("*");
                if (endWith)
                {
                    temp = temp.TrimEnd('*');
                }

                if (temp != string.Empty)
                {
                    CriterionRequest c = new CriterionRequest()
                    {
                        LogicOp = logicOp,
                        PropertyName = string.IsNullOrEmpty(propertyName) ? paramName : propertyName,
                        Value = temp
                    };
                    if (startWith && endWith)
                    {
                        c.CriteriaOp = CriteriaOP.Like;
                    }
                    else if (startWith)
                    {
                        c.CriteriaOp = CriteriaOP.RightLike;
                    }
                    else if (endWith)
                    {
                        c.CriteriaOp = CriteriaOP.LeftLike;
                    }
                    else
                    {
                        c.CriteriaOp = CriteriaOP.Equal;
                    }
                    return c;
                }
            }
            return null;
        }
        static CriterionRequest createCriterionByBoolean(string value, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And)
        {
            if (!string.IsNullOrEmpty(value))
            {
                var lowerValue = value.ToLower();
                var result = (lowerValue == "true" || lowerValue == "on" || lowerValue == "1" || lowerValue == "yes");
                return new CriterionRequest()
                {
                    PropertyName = string.IsNullOrEmpty(propertyName) ? paramName : propertyName,
                    CriteriaOp = CriteriaOP.Equal,
                    LogicOp = logicOp,
                    Value = result
                };
            }
            return null;
        }
        static CriterionRequest createCriterionByNumberic<T>(string value, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And) where T : struct
        {
            if (!string.IsNullOrEmpty(value))
            {
                var n = ConvertHelper.ConvertToNullable<T>(value) as Nullable<T>;
                if (n.HasValue)
                {
                    return new CriterionRequest()
                    {
                        PropertyName = string.IsNullOrEmpty(propertyName) ? paramName : propertyName,
                        CriteriaOp = CriteriaOP.Equal,
                        LogicOp = logicOp,
                        Value = n.Value
                    };
                }

            }
            return null;
        }
        static CriterionRequest createCriterionByNumberic<T>(string value1, string value2, string paramName1, string paramName2, string propertyName, LogicOP logicOp = LogicOP.And) where T : struct
        {
            if (!string.IsNullOrEmpty(value1) || !string.IsNullOrEmpty(value2))
            {
                var n1 = ConvertHelper.ConvertToNullable<T>(value1) as Nullable<T>;
                var n2 = ConvertHelper.ConvertToNullable<T>(value2) as Nullable<T>;

                if (n1.HasValue || n2.HasValue)
                {
                    var c = new CriterionRequest()
                    {
                        LogicOp = logicOp,
                        PropertyName = propertyName
                    };

                    if (n1.HasValue && n2.HasValue)
                    {
                        c.CriteriaOp = CriteriaOP.Between;
                        c.Value = new T[] { n1.Value, n2.Value };
                    }
                    else if (n1.HasValue)
                    {
                        c.CriteriaOp = CriteriaOP.GreatThanEqual;
                        c.Value = n1.Value;
                    }
                    else
                    {
                        c.CriteriaOp = CriteriaOP.LessThan;
                        c.Value = n2.Value;
                    }
                    return c;
                }
            }
            return null;
        }

        public static CriterionRequest CreateCriterionByString(this Controller ctrl, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And)
        {
            var value = ctrl.Request.Params[paramName];
            return createCriterionByString(value, paramName, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByString(this PagingParameter pagingParam, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And)
        {
            var value = pagingParam.Query.ContainsKey(paramName) ? pagingParam.Query[paramName] : string.Empty;
            return createCriterionByString(value, paramName, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByString(this Dictionary<string, string> dic, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And)
        {
            var value = dic.ContainsKey(paramName) ? dic[paramName] : string.Empty;
            return createCriterionByString(value, paramName, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByString(string propertyName, string value, LogicOP logicOp = LogicOP.And)
        {
            return createCriterionByString(value, propertyName, "", logicOp);
        }

        public static CriterionRequest CreateCriterionByBoolean(this Controller ctrl, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And)
        {
            var value = ctrl.Request.Params[paramName];
            return createCriterionByBoolean(value, paramName, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByBoolean(this PagingParameter pagingParam, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And)
        {
            var value = pagingParam.Query.ContainsKey(paramName) ? pagingParam.Query[paramName] : string.Empty;
            return createCriterionByBoolean(value, paramName, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByBoolean(this Dictionary<string, string> dic, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And)
        {
            var value = dic.ContainsKey(paramName) ? dic[paramName] : string.Empty;
            return createCriterionByBoolean(value, paramName, propertyName, logicOp);
        }

        public static CriterionRequest CreateCriterionByNumberic<T>(this Controller ctrl, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And) where T : struct
        {
            var value = ctrl.Request.Params[paramName];
            return createCriterionByNumberic<T>(value, paramName, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByNumberic<T>(this PagingParameter pagingParam, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And) where T : struct
        {
            var value = pagingParam.Query.ContainsKey(paramName) ? pagingParam.Query[paramName] : string.Empty;
            return createCriterionByNumberic<T>(value, paramName, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByNumberic<T>(this Dictionary<string, string> dic, string paramName, string propertyName = "", LogicOP logicOp = LogicOP.And) where T : struct
        {
            var value = dic.ContainsKey(paramName) ? dic[paramName] : string.Empty;
            return createCriterionByNumberic<T>(value, paramName, propertyName, logicOp);
        }

        public static CriterionRequest CreateCriterionByNumberic<T>(this Controller ctrl, string paramName1, string paramName2, string propertyName, LogicOP logicOp = LogicOP.And) where T : struct
        {
            var value1 = ctrl.Request.Params[paramName1];
            var value2 = ctrl.Request.Params[paramName2];
            return createCriterionByNumberic<T>(value1, value2, paramName1, paramName2, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByNumberic<T>(this PagingParameter pagingParam, string paramName1, string paramName2, string propertyName, LogicOP logicOp = LogicOP.And) where T : struct
        {
            var value1 = pagingParam.Query.ContainsKey(paramName1) ? pagingParam.Query[paramName1] : string.Empty;
            var value2 = pagingParam.Query.ContainsKey(paramName2) ? pagingParam.Query[paramName2] : string.Empty;
            return createCriterionByNumberic<T>(value1, value2, paramName1, paramName2, propertyName, logicOp);
        }
        public static CriterionRequest CreateCriterionByNumberic<T>(this Dictionary<string, string> dic, string paramName1, string paramName2, string propertyName, LogicOP logicOp = LogicOP.And) where T : struct
        {
            var value1 = dic.ContainsKey(paramName1) ? dic[paramName1] : string.Empty;
            var value2 = dic.ContainsKey(paramName2) ? dic[paramName2] : string.Empty;
            return createCriterionByNumberic<T>(value1, value2, paramName1, paramName2, propertyName, logicOp);
        }

        public static OrderByRequest CreateOrder(this PagingParameter pagingParam)
        {
            if (!string.IsNullOrEmpty(pagingParam.SortProperty))
            {
                var orderOP = (pagingParam.SortDirection == "desc") ? OrderOP.Desc : OrderOP.Asc;
                return new OrderByRequest()
                {
                    OrderOp = orderOP,
                    PropertyName = pagingParam.SortProperty
                };
            }
            return null;
        }
    }
}
